package com.satan.novel.config.wrapper;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author: Demon
 * @Date: 2024/1/20 20:03
 * @Description: XSS 过滤处理
 **/
// XssHttpServletRequestWrapper 类继承自 HttpServletRequestWrapper，用于对 HTTP 请求参数进行 XSS 过滤处理
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {

    // 定义一个静态 Map，存储需要替换的 XSS 攻击字符及其对应的转义字符串
    private static final Map<String, String> REPLACE_RULE = new HashMap<>();

    // 初始化替换规则，在类加载时执行
    static {
        REPLACE_RULE.put("<", "&lt;"); // 将小于号 '<' 替换为它的 HTML 实体形式 '&lt;'
        REPLACE_RULE.put(">", "&gt;"); // 将大于号 '>' 替换为它的 HTML 实体形式 '&gt;'
        // 可在此处添加更多 XSS 防御相关的替换规则
    }

    // 构造方法，传入原始请求对象并调用父类构造器
    public XssHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
    }

    // 重写 getParameterValues 方法，获取请求参数值并进行 XSS 过滤
    @Override
    public String[] getParameterValues(String name) {
        // 调用父类方法获取原始参数值数组
        String[] values = super.getParameterValues(name);

        // 如果参数存在，则进行 XSS 过滤处理
        if (values != null) {
            int length = values.length;
            // 创建一个新的字符串数组，用于存储过滤后的参数值
            String[] escapeValues = new String[length];

            // 遍历原始参数值数组，并对每个值进行 XSS 替换操作
            for (int i = 0; i < length; i++) {
                escapeValues[i] = values[i];
                int index = i;

                // 对当前参数值应用所有替换规则
                REPLACE_RULE.forEach((k, v) -> escapeValues[index] = escapeValues[index].replaceAll(k, v));
            }
            return escapeValues; // 返回过滤后的参数值数组
        }

        // 如果参数不存在，则返回空数组
        return new String[0];
    }
}
